
class Bitmap
  attr_accessor :filename, :filesize, :height, :width, :type

  # format type
  BITMAPCOREHEADER = 0 # => 12 byte
  BITMAPINFOHEADER = 1 # => 40 byte
  BITMAPV4HEADER   = 2 # => 108 byte
  BITMAPV5HEADER   = 3 # => 124 byte

  class NoBitmapError < Exception; end
  class NoImplementedError < Exception; end
  class UnknownFormatError < Exception; end

  def initialize(filename)
    @filename = filename

    File.open(@filename, 'rb') do |bitmap|
      parse_file_header(bitmap)
      parse_information_header(bitmap)
    end

  end

  def parse_file_header(io)
    header = io.read(14)

    params = header.unpack("A2ISSI")

    puts "Bitmap File Header ----"
    puts "params[0] => #{params[0]}" # => ファイルタイプ
    puts "params[1] => #{params[1]}" # => ファイルサイズ
    puts "params[2] => #{params[2]}" # => 予約1
    puts "params[3] => #{params[3]}" # => 予約2
    puts "params[4] => #{params[4]}" # => データまでのオフセット

    @filesize = params[1]
    @offset = params[4]
  end

  def parse_information_header(io)
    buf = io.read(4)

    header_size = buf.unpack("I")[0]

    puts "Bitmap Information Header ----"
    puts "header_size => #{header_size}"   # => Bitmap Information Header ヘッダサイズ

    @header_size = header_size

    if header_size == 12
      raise NoImplementedError "BITMAPCOREHEADER"
    elsif header_size == 40
      header = io.read(header_size)
      params = header.unpack("iiSSIIiiII")

      puts "params[0] => #{params[0]}" # => 画像の幅
      puts "params[1] => #{params[1]}" # => 画像の高さ
      puts "params[2] => #{params[2]}" # => プレーン数
      puts "params[3] => #{params[3]}" # => 色ビット数
      puts "params[4] => #{params[4]}" # => 圧縮形式
      puts "params[5] => #{params[5]}" # => 画像データサイズ
      puts "params[6] => #{params[6]}" # => 水平解像度
      puts "params[7] => #{params[7]}" # => 垂直解像度
      puts "params[8] => #{params[8]}" # => 格納パレット数
      puts "params[9] => #{params[9]}" # => 重要色数

      @height = params[1]
      @width  = params[0]
      @type   = BITMAPCOREHEADER
    elsif header_size == 108
      raise NoImplementedError "BITMAPV4HEADER"
    elsif header_size == 124
      raise NoImplementedError "BITMAPV5HEADER"
    else
      # unknown data
      raise UnknownFormatError
    end
  end
end

bm = Bitmap.new('sample1.bmp')

puts "filename: #{bm.filename}"
puts "filesize: #{bm.filesize}"

puts "height: #{bm.height}"
puts "width : #{bm.width}"
puts "type  : #{bm.type}"

